﻿using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Hue_Demo_PCL.Models;
using Hue_Demo_PCL.Services;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace Hue_Demo_PCL.ViewModels
{
    public class HueControlViewModel : INotifyPropertyChanged
    {
        private HueService _hueService;

        public HueControlViewModel() 
        {
            _hueService = new HueService();

        }

        private async void GetBridgeAvailability()
        {
            bool available = await _hueService.IsBridgeAvailable();
            if (!available)
            {
                ConnectionError = "Could not connect to Hue bridge. Are you connected to the router?";
            }
        }


        #region UserName (string)
        private string _userName = "";
        public string UserName
        {
            get { return _userName; }
            set
            {
                _userName = value;
                RaisePropertyChanged("UserName");
            }
        }
        #endregion

        #region BridgeIP (string)
        private string _bridgeIP = "192.168.1.2";
        public string BridgeIP
        {
            get { return _bridgeIP; }
            set
            {
                _bridgeIP = value;
                RaisePropertyChanged("BridgeIP");
            }
        }
        #endregion

        #region DebugValue (string)
        private string _debugValue = "[waiting for response]";
        public string DebugValue
        {
            get { return _debugValue; }
            set
            {
                _debugValue = value;
                RaisePropertyChanged("DebugValue");
            }
        }
        #endregion
        
        #region ConnectionError (string)
        private string _connectionError = "";
        public string ConnectionError
        {
            get { return _connectionError; }
            set
            {
                _connectionError = value;
                RaisePropertyChanged("ConnectionError");
            }
        }
        #endregion
        
        #region HueLight1 (HueLight)
        private HueLight _hueLight1 = new HueLight() { Index = 1 };
        public HueLight HueLight1
        {
            get { return _hueLight1; }
            set
            {
                _hueLight1 = value;
                RaisePropertyChanged("HueLight1");
            }
        }
        #endregion

        #region HueLight2 (HueLight)
        private HueLight _hueLight2 = new HueLight() { Index = 2 };
        public HueLight HueLight2
        {
            get { return _hueLight2; }
            set
            {
                _hueLight2 = value;
                RaisePropertyChanged("HueLight2");
            }
        }
        #endregion

        #region HueLight3 (HueLight)
        private HueLight _hueLight3 = new HueLight() { Index = 3 };
        public HueLight HueLight3
        {
            get { return _hueLight3; }
            set
            {
                _hueLight3 = value;
                RaisePropertyChanged("HueLight3");
            }
        }
        #endregion
        
        #region IsWorking (bool)
        private bool _isWorking = false;
        public bool IsWorking
        {
            get { return _isWorking; }
            set
            {
                _isWorking = value;
                RaisePropertyChanged("IsWorking");
            }
        }
        #endregion

        #region IsUserRegistered (bool)
        private bool _isUserRegistered = false;
        public bool IsUserRegistered
        {
            get { return _isUserRegistered; }
            set
            {
                _isUserRegistered = value;
                RaisePropertyChanged("IsUserRegistered");
            }
        }
        #endregion

        #region UpdateLight1 Command
        private RelayCommand _updateLight1;

        /// <summary>
        /// Gets the UpdateLight1.
        /// </summary>
        public RelayCommand UpdateLight1
        {
            get
            {
                return _updateLight1
                    ?? (_updateLight1 = new RelayCommand(
                    async () =>
                    {
                        if (IsWorking)
                            return;
                        await UpdateLight(HueLight1);
                        RaisePropertyChanged("HueLight1");
                    }, () => !IsWorking));
            }
        }
        #endregion

        #region UpdateLight2 Command
        private RelayCommand _updateLight2;

        /// <summary>
        /// Gets the UpdateLight2.
        /// </summary>
        public RelayCommand UpdateLight2
        {
            get
            {
                return _updateLight2
                    ?? (_updateLight2 = new RelayCommand(
                    async () =>
                    {
                        if (IsWorking)
                            return;
                        await UpdateLight(HueLight2);
                        RaisePropertyChanged("HueLight2");
                    }, () => !IsWorking));
            }
        }
        #endregion

        #region UpdateLight3 Command
        private RelayCommand _updateLight3;

        /// <summary>
        /// Gets the UpdateLight3.
        /// </summary>
        public RelayCommand UpdateLight3
        {
            get
            {
                return _updateLight3
                    ?? (_updateLight3 = new RelayCommand(
                    async () =>
                    {
                        if (IsWorking)
                            return;
                        await UpdateLight(HueLight3);
                        RaisePropertyChanged("HueLight3");
                    }, () => !IsWorking));
                
            }
        }
        #endregion

        #region CycleLights Command
        private RelayCommand _cycleLights;

        /// <summary>
        /// Gets the CycleLights.
        /// </summary>
        public RelayCommand CycleLights
        {
            get
            {
                return _cycleLights
                    ?? (_cycleLights = new RelayCommand(
                    async () =>
                    {
                        HueLight tempLight = HueLight1;
                        HueLight1 = HueLight2;
                        HueLight1.Index = 1;
                        HueLight2 = HueLight3;
                        HueLight2.Index = 2;
                        HueLight3 = tempLight;
                        HueLight3.Index = 3;

                        await UpdateLight(HueLight1);
                        await UpdateLight(HueLight2);
                        await UpdateLight(HueLight3);
                        RaisePropertyChanged("HueLight1");
                        RaisePropertyChanged("HueLight2");
                        RaisePropertyChanged("HueLight3");

                    }));
            }
        }
        #endregion

        #region GetLights Command

        private RelayCommand _getLights;

        /// <summary>
        /// Gets the GetLights.
        /// </summary>
        public RelayCommand GetLights
        {
            get
            {
                return _getLights
                    ?? (_getLights = new RelayCommand(
                    async () =>
                    {
                        try
                        {
                            _hueLight1 = await _hueService.GetLight(1);
                            _hueLight2 = await _hueService.GetLight(2);
                            _hueLight3 = await _hueService.GetLight(3);
                            
                        }
                        catch(Exception e)
                        {
                            ConnectionError = "Could not connect to Hue bridge. Are you connected to the router?";
                            
                        }
                        RaisePropertyChanged("HueLight1");
                        RaisePropertyChanged("HueLight2");
                        RaisePropertyChanged("HueLight3");

                    }));
            }
        }
        #endregion

        #region UpdateSettings Command
        private RelayCommand _updateSettings;

        /// <summary>
        /// Gets the UpdateSettings.
        /// </summary>
        public RelayCommand UpdateSettings
        {
            get
            {
                return _updateSettings
                    ?? (_updateSettings = new RelayCommand(
                    async () =>
                    {
                        if (IsWorking)
                            return;
                        UpdateStatus(true);
                        string updateResult = await _hueService.UpdateSettings(_bridgeIP, _userName);
                        if (updateResult.StartsWith("Error"))
                        {
                            ConnectionError = "Could not connect to Hue bridge. Are you connected to the router?";
                        }
                        else
                        {
                            try
                            {
                                _hueLight1 = await _hueService.GetLight(1);
                                _hueLight2 = await _hueService.GetLight(2);
                                _hueLight3 = await _hueService.GetLight(3);

                            }
                            catch (Exception e)
                            {
                                ConnectionError = "Could not connect to Hue bridge. Are you connected to the router?";
                            }
                            RaisePropertyChanged("HueLight1");
                            RaisePropertyChanged("HueLight2");
                            RaisePropertyChanged("HueLight3"); 
                        }
                        UpdateStatus(false);

                    }));
            }
        }
        #endregion

        private void UpdateStatus(bool isUpdating)
        {
            IsWorking = isUpdating;
            UpdateLight1.RaiseCanExecuteChanged();
            UpdateLight2.RaiseCanExecuteChanged();
            UpdateLight3.RaiseCanExecuteChanged();
            UpdateSettings.RaiseCanExecuteChanged();            
        }

        public async Task UpdateLight(HueLight hl)
        {
            if (hl != null)
            {
                UpdateStatus(true);
                hl.UpdateHueSat();
                string result = await _hueService.SetLight(hl);
                Debug.WriteLine(result);
                UpdateStatus(false);
            }
        }

        public async Task<string> SetUser(string userToCheck, bool isNew)
        {
            string result = await _hueService.SetupUser(userToCheck, isNew);
            return result;
        }

        public async Task<HueSettings> GetHueBridge()
        {
            HueSettings resultSettings = await _hueService.GetBridgeIP();
            return resultSettings;
        }

        public HueService GetHueService()
        {
            if (_hueService == null)
                _hueService = new HueService();
            return _hueService;
        }
        
        public event PropertyChangedEventHandler PropertyChanged;

        protected void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }     
    }
}
